package org.qrd.openmayyam;

import org.osgi.framework.BundleContext;

import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
import org.osgi.service.http.NamespaceException;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import java.io.File;
import java.io.IOException;

import java.net.MalformedURLException;

/**
 * Listens for new WAR files at intervals
 *
 * @author Adarsh
 * @author Sivaraman
 */
public class MainThread extends Thread {

    /**
     * Object for the custom class loader
     */
    ClassLoader cl;
    /**
     * This is used to get the reference of org.osgi.service.http.HttpService.
     */
    private HttpService httpService=null;
    /**
     * It is used to create a default Http context.
     */
    private HttpContext httpContext;
    int len, i = 0;
    /**
     * context[][] stores the servlets mapping details.
     */
    String contexts[][], wars[];
    File f;

    //CustomClassLoader test = new CustomClassLoader();
     ParseXML parser = new ParseXML();
     HttpServlet[] hs = new HttpServlet[20];
     ExpandWar expandWar = new ExpandWar();
   

    /**
     * Boolean value that determines whether the bundle has been requested to stop or not
     */

    private boolean running = true;
    BundleContext context;

    /**
     * This assigns the context of the bundle that calls it to the instance of the class.
     */
    public void run(BundleContext context) throws Exception {
        this.context = context;
    }

    /**
     * This is the main method that expands all the new WAR files and then parses the web.xml file.
     * The servlets are registered here.
     */

    public static void main(String[] args) {

       MainThread mainThread = new MainThread();
        System.out.println("Starting server");
        mainThread.run();
        System.out.println("server shutdown");
    }
    public void run() {
        while (running) {
            // Get the list of all the WAR files present
            ServerConfiguration serverConfiguration = ServerConfiguration.getServerConfiguration();
            String omHome = serverConfiguration.serverProperties.getProperty("OPEN_MAYYAM_HOME");
            String omDocRoot = serverConfiguration.serverProperties.getProperty("DOC_ROOT");
            String omWebXMLPath = serverConfiguration.serverProperties.getProperty("WEB_XML_PATH");
            String omWarPath = omHome + omDocRoot;
            System.out.println("warpath:"+omWarPath);
            try {

                wars = expandWar.expandAll(omWarPath);
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            // If there are no WAR files, wait for few seconds.
            if (wars == null) {
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                continue;
            }
            // Process through each WAR file.
            int k=0;
            
            for (i = 0; i < wars.length; i++) {

                if (wars[i] == null) break;

//		System.out.println("wars no : " + i);


                f = new File(omWarPath + wars[i] + omWebXMLPath);
                System.out.println("absolutepath"+f.getAbsolutePath());
                try {
                    // parse the web.xml file of the currrent WAR file.

                    contexts = parser.parseXML(f, wars[i]);
                   
                } catch (MalformedURLException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }


                System.out.println("servlet registered : " + wars[i]);
                // For each entry in the web.xml file, register the servlets.
                CustomClassLoader cc = new CustomClassLoader(); 
                
                for (int j = 0; j < contexts.length; j++) {
                	
                    // If there are no entries , then break out.
                    if (contexts[j][0] == null) break;
                   
                    System.out.println("j " + j);
                    // Get the class through a custom class loader, here contexts[j][1] refers to the complete path of the class file
                    // and contexts[i][2] refers to the class name.
                           
                               

                   // Class cls  = cc.loadClass("contexts[j][2]");
                     System.out.println("contexts[j][1] :" + contexts[j][1]);
                     System.out.println("contexts[j][2] :" + contexts[j][2]);
                    // Class<?> cls = cc.getClass(contexts[j][1],contexts[j][2]);
                    // System.out.println("getclass"+cls);
                   
                     //k++;
                    //Class cls = cc.getClass("/home/adarsh/sample/WEB-INF/classes/mypackage/Hello.class", "mypackage.Hello");
                   try {
                        // once we have the class, a new instance is to be created.
                	   
                	   Class<?> cls = cc.getClass(contexts[j][1],contexts[j][2]);
                        hs[k]= (HttpServlet) cls.newInstance();
                        
              
                    } catch (InstantiationException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        // TODO Auto-generated catch block
                       e.printStackTrace();
                    }
                    // In the next 3 steps, a handle for the httpservice as exposed by the bundle is got.
                   ServiceReference serviceReference = context.getServiceReference(HttpService.class.getName());
                    httpService = (HttpService) context.getService(serviceReference);
                    httpContext = httpService.createDefaultHttpContext();
                    //final Dictionary<String, String> initParams = new Hashtable<String, String>();
                    //Dictionary<String,Class<?>> initparams = new HashMap<String,Class<?> >;
                    //initParams.put(wars[i],contexts[j][0]);
                   
                    // httpService.registerServlet("/hello", hs, null, httpContext);
                    try {
                    	 // httpService.unregister(wars[i]+contexts[j][0]);
                        // use the registerservlet method to register the servlets.
                        System.out.println("url: "+wars[i]+contexts[j][0]);
                        //System.out.println("hs : " +hs[j]);
                      //  System.out.println("initparams : "+initParams);
                        System.out.println("hs["+k+"] : " +hs[k]);
                        //registerService(java.lang.String clazz,java.lang.Object service,java.util.Dictionary properties)
                        httpService.registerServlet(wars[i]+contexts[j][0],hs[k],null,httpContext);
                        //httpService.registerResources(contexts[j][0],"/images",httpContext);

                       // httpService.unregister(wars[i]+contexts[j][0]);
                        httpService.createDefaultHttpContext();
                    } catch (ServletException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (NamespaceException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                k++;
                System.out.println("out : "+k);
                
                
            }
            // once all the WAR files have been parsed , wait for few sec.
            try {
            	
                Thread.sleep(50000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /**
     * This method is called to stop the thred by setting the boolean value to false.
     */

    public void stopThread() {
        this.running = false;
    }
}